﻿using System;
using System.IO;
using System.Net;
using System.Linq;
using System.ServiceModel;
using System.ServiceModel.Channels;
using System.ServiceModel.Activation;
using System.ServiceModel.Description;
using System.Collections.Generic;
using System.Text;
using System.Runtime;
using System.Runtime.InteropServices;
using System.Runtime.Remoting.Messaging;
using System.Runtime.Remoting;
using System.Web;
using System.Web.Services;
using System.Web.SessionState;
using System.Threading;
using System.Reflection;

using PickGold.Exceptions;
using PickGold.Util.Proxies;

namespace PickGold.Util.Remoting
{
	/// <summary>
	/// "%ProgramFiles%\Microsoft SDKs\Windows\v6.0A\bin\SvcUtil.exe"
	/// </summary>
	[Serializable]
	[ComVisible(true)]
	[ClassInterface(ClassInterfaceType.AutoDispatch)]
	[WebService(Namespace = "hsj://hong.shi.jin/")]
	[WebServiceBinding(ConformsTo = WsiProfiles.BasicProfile1_1)]
	[ServiceBehavior(UseSynchronizationContext = false, Namespace = "hsj://hong.shi.jin/", ConcurrencyMode = ConcurrencyMode.Multiple, InstanceContextMode = InstanceContextMode.Single)]
	[AspNetCompatibilityRequirements(RequirementsMode = AspNetCompatibilityRequirementsMode.Allowed)]
	public class MethodInvoker : WebService, IHttpHandler, IMethodInvoker, IMethodInvokerDuplex, IRequiresSessionState
	{
		private static readonly object InvokingKey = new object();
		/// <summary>
		/// 只调用远程，否则可能会调用本地；
		/// </summary>
		public static bool OnlyRemote
		{
			set
			{
				MethodInvokerWcfClient.OnlyRemote = value;
			}
			get
			{
				return MethodInvokerWcfClient.OnlyRemote;
			}
		}

		#region ServiceHost

		/// <summary>
		/// 取WCF服务
		/// </summary>
		/// <returns>WCF服务</returns>
		public static ServiceHost GetService()
		{
			return new ServiceHost(new MethodInvoker());
		}

		/// <summary>
		/// 添加WCF服务器终节点；
		/// </summary>
		/// <param name="service">WCF</param>
		/// <param name="binding">Binding</param>
		/// <param name="address">Uri</param>
		/// <returns>WCF服务器终节点</returns>
		public static ServiceEndpoint AddServiceEndpoint(ServiceHost service, Binding binding, Uri address)
		{
			return service.AddServiceEndpoint(typeof(IMethodInvoker), binding, address);
		}

		/// <summary>
		/// 启动WCF服务
		/// </summary>
		/// <param name="timeout">超时时间，零表示不设置；</param>
		/// <param name="async">是否异步打开；</param>
		/// <param name="addresses">地址序列；</param>
		/// <returns>服务所在的线程；</returns>
		public static Thread Start(TimeSpan timeout, bool async, params string[] addresses)
		{
			if (addresses == null || addresses.Length == 0)
				return null;

			var us = new Uri[addresses.Length];
			for (var i = 0; i < addresses.Length; i++)
				us[i] = new Uri(addresses[i]);
			return MethodInvoker.Start(timeout, async, us);
		}

		/// <summary>
		/// 启动WCF服务
		/// </summary>
		/// <param name="timeout">超时时间，零表示不设置；</param>
		/// <param name="async">是否异步打开；</param>
		/// <param name="addresses">地址序列；</param>
		/// <returns>服务所在的线程；</returns>
		public static Thread Start(TimeSpan timeout, bool async, params Uri[] addresses)
		{
			var sh = MethodInvoker.GetService();

			var type = typeof(IMethodInvoker);

			var tcp = new NetTcpBinding(SecurityMode.None);
			tcp.MaxReceivedMessageSize = int.MaxValue;
			tcp.ReaderQuotas.MaxArrayLength = int.MaxValue;

			var http = new WSHttpBinding(SecurityMode.None);
			http.MaxReceivedMessageSize = int.MaxValue;
			http.ReaderQuotas.MaxArrayLength = int.MaxValue;

			var pipe = new NetNamedPipeBinding(NetNamedPipeSecurityMode.None);
			pipe.MaxReceivedMessageSize = int.MaxValue;
			pipe.ReaderQuotas.MaxArrayLength = int.MaxValue;

			foreach (var uri in addresses)
			{
				if (string.Compare(uri.Scheme, tcp.Scheme, StringComparison.OrdinalIgnoreCase) == 0)
				{
					MethodInvoker.AddServiceEndpoint(sh, tcp, uri);
					continue;
				}

				if (string.Compare(uri.Scheme, http.Scheme, StringComparison.OrdinalIgnoreCase) == 0)
				{
					MethodInvoker.AddServiceEndpoint(sh, http, uri);
					continue;
				}

				if (string.Compare(uri.Scheme, pipe.Scheme, StringComparison.OrdinalIgnoreCase) == 0)
				{
					MethodInvoker.AddServiceEndpoint(sh, pipe, uri);
					continue;
				}
			}
			return MethodInvoker.Start(sh, timeout, async);
		}

		/// <summary>
		/// 启动WCF服务
		/// </summary>
		/// <param name="service">WCF服务</param>
		/// <param name="timeout">超时时间，零表示不设置；</param>
		/// <param name="async">是否异步打开；</param>
		/// <returns>服务所在的线程；</returns>
		public static Thread Start(ServiceHost service, TimeSpan timeout, bool async)
		{
			if (async)
			{
				var pts = new ParameterizedThreadStart(p =>
				{
					var ps = p as object[];
					MethodInvoker.Start(ps[0] as ServiceHost, (TimeSpan)ps[1], false);
				});
				var thread = new Thread(pts);
				thread.IsBackground = true;
				thread.Start(new object[] { service, timeout });
				return thread;
			}

			if (timeout > TimeSpan.Zero)
				service.Open(timeout);
			else
				service.Open();
			return Thread.CurrentThread;
		}

		#endregion

		/// <summary>
		/// 调用事件
		/// </summary>
		public event InvokeMessageEventHandler Invoking
		{
			add
			{
				this.Events.AddHandler(InvokingKey, value);
			}
			remove
			{
				this.Events.RemoveHandler(InvokingKey, value);
			}
		}

		#region IMethodInvoker 成员

		private MethodInvokerReturnMessage Invoke(IMethodCallMessage message)
		{
			if (message == null)
				return new MethodInvokerReturnMessage(null, null, null, null);

			var t = message.MethodBase.DeclaringType;
			if (!string.IsNullOrEmpty(message.TypeName))
				t = Type.GetType(message.TypeName, false, true);
			if (t == null)
				t = message.MethodBase.DeclaringType;
			CMessage.ThreadHandler = MethodInvoker.GetImplementByType(t);
			if (CMessage.ThreadHandler == null)
				return new MethodInvokerReturnMessage(new NotImplementedException("The interface [" + message.MethodBase.DeclaringType + "] not implemented."), message);

			var e = Reflector<InvokeMessageEventArgs>.DefaultValue;
			var h = this.Events[InvokingKey] as InvokeMessageEventHandler;
			if (h != null)
			{
				e = new InvokeMessageEventArgs(message);
				h(this, e);
				if (e.ReturnMessage != null)
					return new MethodInvokerReturnMessage(e.ReturnMessage, message);
			}
			var rm = message.Invoke(CMessage.ThreadHandler, message.MethodBase);
			if (h != null)
			{
				e.ReturnMessage = rm;
				h(this, e);
			}
			return new MethodInvokerReturnMessage(rm, message);
		}

		[WebMethod(MessageName = "Invoke", Description = "调用远程方法；")]
		byte[] IMethodInvoker.Invoke(byte[] message)
		{
			var ms = new MemoryStream();
			var cm = message.Deserialize();//反序列化调用。
			var mcm = cm as IMethodCallMessage;
			if (mcm == null)
			{
				var m = cm as CMethodCallMessage;
				if (m != null)
				{
					m.ProcessPropertiesProxy(false);
					mcm = new MethodInvokerCallMessage(m);
				}
			}
			CMessage.ThreadMessage = mcm;
			var mrm = this.Invoke(mcm);
			var rm = mrm.Storage;
			rm.ProcessPropertiesProxy(true);
			if (rm.Exception != null && !rm.Exception.GetType().IsSerializable)
				rm.Exception = new WrapSerializableException(rm.Exception);
			rm.Serialize(ms);//序列化结果。
			message = ms.ToArray();
			return message;
		}

		[WebMethod(MessageName = "GetDateTime", Description = "取指定时间或服务器全球时间，一般用作测试；")]
		DateTime IMethodInvoker.GetDateTime(string dateTime)
		{
			if (string.IsNullOrEmpty(dateTime))
				return DateTime.UtcNow;

			return DateTime.Parse(dateTime);
		}

		IAsyncResult IMethodInvoker.BeginAsyncInvoke(byte[] message, AsyncCallback callback, object state)
		{
			return this.BeginInvoke(new MemoryStream(message), callback, state);
		}

		byte[] IMethodInvoker.EndAsyncInvoke(IAsyncResult result)
		{
			var ms = new MemoryStream();
			this.EndInvoke(result, ms);
			return ms.ToArray();
		}

		/// <summary>
		/// 调用远程方法
		/// </summary>
		/// <param name="input">输入消息</param>
		/// <param name="output">输出消息</param>
		public void Invoke(Stream input, Stream output)
		{
			var cm = input.Deserialize();//反序列化调用。
			var mcm = cm as IMethodCallMessage;
			if (mcm == null)
			{
				var m = cm as CMethodCallMessage;
				if (m != null)
				{
					m.ProcessPropertiesProxy(false);
					mcm = new MethodInvokerCallMessage(m);
				}
			}
			CMessage.ThreadMessage = mcm;
			var mrm = this.Invoke(mcm);
			var rm = mrm.Storage;
			rm.ProcessPropertiesProxy(true);
			if (rm.Exception != null && !rm.Exception.GetType().IsSerializable)
				rm.Exception = new WrapSerializableException(rm.Exception);
			rm.Serialize(output);//序列化结果。
		}

		/// <summary>
		/// 开始异步调用远程方法
		/// </summary>
		/// <param name="input">输入消息</param>
		/// <param name="callback">回调</param>
		/// <param name="state">用户数据</param>
		/// <returns>异步结果</returns>
		public IAsyncResult BeginInvoke(Stream input, AsyncCallback callback, object state)
		{
			var ms = new MemoryStream();
			var cm = input.Deserialize();//反序列化调用。
			var mcm = cm as IMethodCallMessage;
			if (mcm == null)
			{
				var m = cm as CMethodCallMessage;
				if (m != null)
				{
					m.ProcessPropertiesProxy(false);
					m.Args[m.InArgs.Length - 2] = callback;
					m.InArgs[m.InArgs.Length - 2] = callback;
					m.Args[m.InArgs.Length - 1] = state;
					m.InArgs[m.InArgs.Length - 2] = state;
					mcm = new MethodInvokerCallMessage(m);
				}
			}
			CMessage.ThreadMessage = mcm;
			var mrm = this.Invoke(mcm);
			CMessage.ThreadMessage = mrm;
			var ar = new AsyncInvokerResult(-1);
			ar.Call = mcm;
			ar.ResultWrap.WrapReturn = mrm;
			ar.ResultWrap.WrapResult = mrm.ReturnValue as IAsyncResult;
			return ar;
		}

		/// <summary>
		/// 结束异步调用远程方法
		/// </summary>
		/// <param name="result">异步结果</param>
		/// <param name="output">输出消息</param>
		public void EndInvoke(IAsyncResult result, Stream output)
		{
			var ar = result as AsyncInvokerResult;
			var mrm = ar.ResultWrap.WrapReturn as IMethodReturnMessage;
			CMessage.ThreadMessage = ar.Call;
			CMessage.ThreadHandler = ar.Real;
			if (ar.Call.MethodBase.Name.StartsWith("Begin", StringComparison.OrdinalIgnoreCase))
			{
				var ec = ar.Call.MethodBase.DeclaringType.GetMethod("End" + ar.Call.MethodBase.Name.Substring(5), new Type[] { typeof(IAsyncResult), });
				if (ec != null)
				{
					this.EndInvoke(ar, ec, output);
					return;
				}
			}

			var cb = ar.Call.MethodBase.DeclaringType.GetMethod(ar.Call.MethodBase.Name, new Type[] { typeof(IAsyncResult), });
			if (cb == null)
				new MethodInvokerReturnMessage(new NotImplementedException("The async end/callback method [" + ar.Call.MethodBase.Name + "] not declared."), null).Serialize(output);
			else
				this.EndInvoke(ar, cb, output);
		}

		private void EndInvoke(AsyncInvokerResult result, MethodBase endMethod, Stream output)
		{
			var mcm = new CMethodCallMessage();
			var ps = endMethod.GetParameters();
			mcm.Args = new object[] { result.ResultWrap.WrapResult, };
			mcm.ArgNames = ps.Select(item => item.Name).ToArray();
			mcm.InArgs = mcm.Args;
			mcm.ArgNames = mcm.ArgNames;
			mcm.MethodBase = endMethod;
			mcm.MethodName = endMethod.Name;
			mcm.MethodSignature = ps.Select(item => item.ParameterType).ToArray();
			mcm.TypeName = endMethod.ReflectedType.FullName;
			mcm.ProcessPropertiesProxy(true);
			this.Invoke(new MethodInvokerCallMessage(mcm)).Serialize(output);//序列化结果。
		}

		#endregion

		#region IHttpHandler 成员

		bool IHttpHandler.IsReusable
		{
			get
			{
				return true;
			}
		}

		void IHttpHandler.ProcessRequest(HttpContext context)
		{
			if (context.Request.ContentLength == 0)
			{
				context.Response.ContentType = Mime.GetMime(Mime.TXT);
				context.Response.AddHeader(HttpHeaderKey.LAST_MODIFIED, context.Timestamp.ToString("R"));
				context.Response.AddHeader(HttpHeaderKey.ETAG, context.Timestamp.GetJsTicks().ToString("X"));
				context.Response.Write(context.Timestamp.ToString());
				return;
			}

			var cm = context.Request.InputStream.Deserialize();
			var mcm = cm as IMethodCallMessage;
			if (mcm == null)
			{
				var m = cm as CMethodCallMessage;
				if (m != null)
				{
					m.ProcessPropertiesProxy(false);
					mcm = new MethodInvokerCallMessage(m);
				}
			}
			CMessage.ThreadMessage = mcm;
			var mrm = this.Invoke(mcm);
			var rm = mrm.Storage;
			rm.ProcessPropertiesProxy(true);
			rm.Serialize(context.Response.OutputStream);
		}

		#endregion

		#region Create

		/// <summary>
		/// 使用应用程序配置文件中的默认目标终结点初始化 API 类的新实例或代理。
		/// </summary>
		/// <param name="empty">DBNull.Value</param>
		/// <exception cref="System.InvalidOperationException">配置文件中没有默认的终结点信息，或者文件中有多个终结点，或者没有配置文件。</exception>
		public static API Create<API>() where API : class
		{
			var api = MethodInvoker.GetImplement<API>();
			if (api != null)
				return new MethodInvokerLocaleProxy<API>(api).GetTransparentProxy() as API;

			return new MethodInvokerRemoteProxy<API>().GetTransparentProxy() as API;
		}
		/// <summary>
		/// 使用应用程序配置文件中的默认目标终结点初始化 API 类的新实例或代理。
		/// </summary>
		/// <param name="address">远程地址；</param>
		/// <exception cref="System.InvalidOperationException">配置文件中没有默认的终结点信息，或者文件中有多个终结点，或者没有配置文件。</exception>
		public static API Create<API>(Uri address) where API : class
		{
			var api = MethodInvoker.GetImplement<API>();
			if (api != null)
				return new MethodInvokerLocaleProxy<API>(api).GetTransparentProxy() as API;

			var tcp = new NetTcpBinding(SecurityMode.None);
			tcp.MaxReceivedMessageSize = int.MaxValue;
			tcp.ReaderQuotas.MaxArrayLength = int.MaxValue;

			var http = new WSHttpBinding(SecurityMode.None);
			http.MaxReceivedMessageSize = int.MaxValue;
			http.ReaderQuotas.MaxArrayLength = int.MaxValue;

			var pipe = new NetNamedPipeBinding(NetNamedPipeSecurityMode.None);
			pipe.MaxReceivedMessageSize = int.MaxValue;
			pipe.ReaderQuotas.MaxArrayLength = int.MaxValue;

			if (string.Compare(address.Scheme, tcp.Scheme, StringComparison.OrdinalIgnoreCase) == 0)
				return new MethodInvokerRemoteProxy<API>(tcp, new EndpointAddress(address)).GetTransparentProxy() as API;

			if (string.Compare(address.Scheme, http.Scheme, StringComparison.OrdinalIgnoreCase) == 0)
				return new MethodInvokerRemoteProxy<API>(http, new EndpointAddress(address)).GetTransparentProxy() as API;

			if (string.Compare(address.Scheme, pipe.Scheme, StringComparison.OrdinalIgnoreCase) == 0)
				return new MethodInvokerRemoteProxy<API>(pipe, new EndpointAddress(address)).GetTransparentProxy() as API;

			return api;
		}
		/// <summary>
		/// 使用应用程序配置文件中的默认目标终结点初始化 API 类的新实例或代理。
		/// </summary>
		/// <param name="request">Web Request</param>
		public static API Create<API>(WebRequest request) where API : class
		{
			return new MethodInvokerRemoteProxy<API>(new WebRequestClient(request)).GetTransparentProxy() as API;
		}
		/// <summary>
		/// 通过使用 instance 作为客户端应用程序用以连接服务的对象来初始化 API 类的新实例或代理。
		/// </summary>
		/// <param name="instance">客户端应用程序用以连接服务的对象。</param>
		/// <exception cref="System.ArgumentNullException">客户端应用程序用以连接服务的对象实例为 Null。</exception>
		public static API Create<API>(object instance) where API : class
		{
			var api = MethodInvoker.GetImplement<API>();
			if (api != null)
				return new MethodInvokerLocaleProxy<API>(api).GetTransparentProxy() as API;

			var client = MethodInvokerRemoteProxy<API>.GetClient(instance);
			if (client == null)
				return null;

			return new MethodInvokerRemoteProxy<API>(client).GetTransparentProxy() as API;
		}
		/// <summary>
		/// 通过使用 callbackInstance 作为双工对话中的回调对象来初始化 API 类的新实例或代理。
		/// </summary>
		/// <param name="callbackInstance">客户端应用程序用以侦听来自所连接服务的消息的回调对象。</param>
		/// <exception cref="System.ArgumentNullException">回调实例为 Null。</exception>
		/// <exception cref="System.InvalidOperationException">配置文件中没有默认的终结点信息，或者文件中有多个终结点，或者没有配置文件。</exception>
		public static API Create<API>(InstanceContext callbackInstance) where API : class
		{
			var api = MethodInvoker.GetImplement<API>();
			if (api != null)
				return new MethodInvokerLocaleProxy<API>(api).GetTransparentProxy() as API;

			return new MethodInvokerRemoteProxy<API>(callbackInstance).GetTransparentProxy() as API;
		}
		/// <summary>
		/// 使用应用程序配置文件中由 endpointConfigurationName 指定的配置信息来初始化 API 类的新实例或代理。
		/// </summary>
		/// <param name="endpointConfigurationName">应用程序配置文件中的终结点的名称。</param>
		/// <exception cref="System.ArgumentNullException">指定的终结点信息为 Null。</exception>
		/// <exception cref="System.InvalidOperationException">无法找到终结点或者终结点协定无效。</exception>
		public static API Create<API>(string endpointConfigurationName) where API : class
		{
			var api = MethodInvoker.GetImplement<API>();
			if (api != null)
				return new MethodInvokerLocaleProxy<API>(api).GetTransparentProxy() as API;

			return new MethodInvokerRemoteProxy<API>(endpointConfigurationName).GetTransparentProxy() as API;
		}
		/// <summary>
		/// 使用指定的绑定和目标地址初始化 API 类的新实例或代理。
		/// </summary>
		/// <param name="binding">用于调用服务的绑定。</param>
		/// <param name="remoteAddress">服务终结点的地址。</param>
		/// <exception cref="System.ArgumentNullException">绑定为 Null。</exception>
		/// <exception cref="System.ArgumentNullException">远程地址为 Null。</exception>
		public static API Create<API>(Binding binding, EndpointAddress remoteAddress) where API : class
		{
			var api = MethodInvoker.GetImplement<API>();
			if (api != null)
				return new MethodInvokerLocaleProxy<API>(api).GetTransparentProxy() as API;

			return new MethodInvokerRemoteProxy<API>(binding, remoteAddress).GetTransparentProxy() as API;
		}
		/// <summary>
		/// 使用指定的回调服务和终结点配置信息初始化 API 类的新实例或代理。
		/// </summary>
		/// <param name="callbackInstance">客户端用以侦听来自所连接服务的消息的回调对象。</param>
		/// <param name="endpointConfigurationName">应用程序配置文件中的终结点的名称。</param>
		/// <exception cref="System.ArgumentNullException">回调实例为 Null。</exception>
		/// <exception cref="System.ArgumentNullException">终结点为 Null。</exception>
		/// <exception cref="System.InvalidOperationException">无法找到终结点或者终结点协定无效。</exception>
		public static API Create<API>(InstanceContext callbackInstance, string endpointConfigurationName) where API : class
		{
			var api = MethodInvoker.GetImplement<API>();
			if (api != null)
				return new MethodInvokerLocaleProxy<API>(api).GetTransparentProxy() as API;

			return new MethodInvokerRemoteProxy<API>(callbackInstance, endpointConfigurationName).GetTransparentProxy() as API;
		}
		/// <summary>
		/// 使用指定的目标地址和终结点信息初始化 API 类的新实例或代理。
		/// </summary>
		/// <param name="endpointConfigurationName">应用程序配置文件中的终结点的名称。</param>
		/// <param name="remoteAddress">服务的地址。</param>
		/// <exception cref="System.ArgumentNullException">终结点为 Null。</exception>
		/// <exception cref="System.ArgumentNullException">远程地址为 Null。</exception>
		/// <exception cref="System.InvalidOperationException">无法找到终结点或者终结点协定无效。</exception>
		public static API Create<API>(string endpointConfigurationName, EndpointAddress remoteAddress) where API : class
		{
			var api = MethodInvoker.GetImplement<API>();
			if (api != null)
				return new MethodInvokerLocaleProxy<API>(api).GetTransparentProxy() as API;

			return new MethodInvokerRemoteProxy<API>(endpointConfigurationName, remoteAddress).GetTransparentProxy() as API;
		}
		/// <summary>
		/// 初始化 API 类的新实例或代理。
		/// </summary>
		/// <param name="endpointConfigurationName">应用程序配置文件中的终结点的名称。</param>
		/// <param name="remoteAddress">服务的地址。</param>
		/// <exception cref="System.ArgumentNullException">终结点为 Null。</exception>
		/// <exception cref="System.ArgumentNullException">远程地址为 Null。</exception>
		/// <exception cref="System.InvalidOperationException">无法找到终结点或者终结点协定无效。</exception>
		public static API Create<API>(string endpointConfigurationName, string remoteAddress) where API : class
		{
			var api = MethodInvoker.GetImplement<API>();
			if (api != null)
				return new MethodInvokerLocaleProxy<API>(api).GetTransparentProxy() as API;

			return new MethodInvokerRemoteProxy<API>(endpointConfigurationName, remoteAddress).GetTransparentProxy() as API;
		}
		/// <summary>
		/// 初始化 API 类的新实例或代理。
		/// </summary>
		/// <param name="callbackInstance">回调服务。</param>
		/// <param name="binding">用于调用服务的绑定。</param>
		/// <param name="remoteAddress">服务终结点的地址。</param>
		/// <exception cref="System.ArgumentNullException">回调实例为 Null。</exception>
		/// <exception cref="System.ArgumentNullException">绑定为 Null。</exception>
		/// <exception cref="System.ArgumentNullException">远程地址为 Null。</exception>
		public static API Create<API>(InstanceContext callbackInstance, Binding binding, EndpointAddress remoteAddress) where API : class
		{
			var api = MethodInvoker.GetImplement<API>();
			if (api != null)
				return new MethodInvokerLocaleProxy<API>(api).GetTransparentProxy() as API;

			return new MethodInvokerRemoteProxy<API>(callbackInstance, binding, remoteAddress).GetTransparentProxy() as API;
		}
		/// <summary>
		/// 初始化 API 类的新实例或代理。
		/// </summary>
		/// <param name="callbackInstance">客户端用以侦听来自所连接服务的消息的回调对象。</param>
		/// <param name="endpointConfigurationName">应用程序配置文件中的终结点的名称。</param>
		/// <param name="remoteAddress">服务的地址。</param>
		/// <exception cref="System.ArgumentNullException">回调实例为 Null。</exception>
		/// <exception cref="System.ArgumentNullException">终结点为 Null。</exception>
		/// <exception cref="System.ArgumentNullException">远程地址为 Null。</exception>
		/// <exception cref="System.InvalidOperationException">无法找到终结点或者终结点协定无效。</exception>
		public static API Create<API>(InstanceContext callbackInstance, string endpointConfigurationName, EndpointAddress remoteAddress) where API : class
		{
			var api = MethodInvoker.GetImplement<API>();
			if (api != null)
				return new MethodInvokerLocaleProxy<API>(api).GetTransparentProxy() as API;

			return new MethodInvokerRemoteProxy<API>(callbackInstance, endpointConfigurationName, remoteAddress).GetTransparentProxy() as API;
		}
		/// <summary>
		/// 初始化 API 类的新实例或代理。
		/// </summary>
		/// <param name="callbackInstance">客户端用以侦听来自所连接服务的消息的回调对象。</param>
		/// <param name="endpointConfigurationName">应用程序配置文件中的终结点的名称。</param>
		/// <param name="remoteAddress">服务的地址。</param>
		/// <exception cref="System.ArgumentNullException">回调实例为 Null。</exception>
		/// <exception cref="System.ArgumentNullException">终结点为 Null。</exception>
		/// <exception cref="System.ArgumentNullException">远程地址为 Null。</exception>
		/// <exception cref="System.InvalidOperationException">无法找到终结点或者终结点协定无效。</exception>
		public static API Create<API>(InstanceContext callbackInstance, string endpointConfigurationName, string remoteAddress) where API : class
		{
			var api = MethodInvoker.GetImplement<API>();
			if (api != null)
				return new MethodInvokerLocaleProxy<API>(api).GetTransparentProxy() as API;

			return new MethodInvokerRemoteProxy<API>(callbackInstance, endpointConfigurationName, remoteAddress).GetTransparentProxy() as API;
		}

		/// <summary>
		/// 设置 API 接口的实现实例或代理。
		/// </summary>
		/// <typeparam name="API">业务接口</typeparam>
		/// <param name="implement">指定 API 接口的实现实例或代理</param>
		public static void SetImplement<API>(API implement)
		{
			if (!Monitor.TryEnter(Utility.StaticCache.InnerForGetImplement, Fiber.LockTimeout))
				Fiber.ThrowLockTimeoutException(Utility.StaticCache.InnerForGetImplement);
			try
			{
				Utility.StaticCache.InnerForGetImplement[typeof(API)] = implement;
			}
			finally
			{
				Monitor.Exit(Utility.StaticCache.InnerForGetImplement);
			}
		}

		/// <summary>
		/// 设置 API 接口的实现实例或代理。
		/// </summary>
		/// <typeparam name="API">业务接口</typeparam>
		/// <param name="implement">指定 API 接口的实现实例或代理</param>
		public static void SetImplement<API>(Func<API> implement)
		{
			if (!Monitor.TryEnter(Utility.StaticCache.InnerForGetImplement, Fiber.LockTimeout))
				Fiber.ThrowLockTimeoutException(Utility.StaticCache.InnerForGetImplement);
			try
			{
				Utility.StaticCache.InnerForGetImplement[typeof(API)] = implement;
			}
			finally
			{
				Monitor.Exit(Utility.StaticCache.InnerForGetImplement);
			}
		}

		/// <summary>
		/// 获取指定接口的实现实例或代理。
		/// </summary>
		/// <param name="type">接口的类型</param>
		/// <returns>指定接口的实现实例或代理</returns>
		public static object GetImplementByType(Type type)
		{
			var v = Type.Missing;
			if (!Monitor.TryEnter(Utility.StaticCache.InnerForGetImplement, Fiber.LockTimeout))
				Fiber.ThrowLockTimeoutException(Utility.StaticCache.InnerForGetImplement);
			try
			{
				if (Utility.StaticCache.InnerForGetImplement.ContainsKey(type))
				{
					try
					{
						v = Utility.StaticCache.InnerForGetImplement[type];
					}
					catch (Exception x)
					{
						x.WriteEvent();
					}
				}
				if (v != Type.Missing)
				{
					var h = v as Delegate;
					if (h != null)
					{
						v = h.DynamicInvoke(Reflector<object>.EmptyArray);
					}
					else
					{
						type = v as Type;
						if (type != null)
							v = type.GetInstance();
					}
					return v;
				}

				var t = ImplementAttribute.GetImplementedType(type);
				if (t == null)
				{
					try
					{
						Utility.StaticCache.InnerForGetImplement[type] = null;
					}
					catch (Exception x)
					{
						x.WriteEvent();
					}
					return null;
				}

				v = t.GetInstance();
				try
				{
					Utility.StaticCache.InnerForGetImplement[type] = v;
				}
				catch (Exception x)
				{
					x.WriteEvent();
				}
			}
			finally
			{
				Monitor.Exit(Utility.StaticCache.InnerForGetImplement);
			}
			return v;
		}

		/// <summary>
		/// 获取 API 接口的实现实例或代理。
		/// </summary>
		/// <typeparam name="API">业务接口</typeparam>
		/// <returns>指定 API 接口的实现实例或代理</returns>
		public static API GetImplement<API>() where API : class
		{
			if (MethodInvokerWcfClient.OnlyRemote)
				return default(API);

			var o = MethodInvoker.GetImplementByType(typeof(API));
			if (o == null)
				return default(API);

			return (API)o;
		}

		/// <summary>
		/// 关闭代理。
		/// </summary>
		/// <param name="api">代理实例。</param>
		/// <returns>关闭结果：零代理关闭，正数为未关闭，负数为关闭实例。</returns>
		public static int Close(object api)
		{
			if (api == null)
				return int.MaxValue;

			var proxy = RemotingServices.GetRealProxy(api) as IDisposable;
			if (proxy != null)
			{
				proxy.Dispose();
				return 0;
			}

			proxy = api as IDisposable;
			if (proxy != null)
			{
				proxy.Dispose();
				return int.MinValue;
			}

			return int.MaxValue;
		}

		#endregion

		/// <summary>
		/// 创建双向回调的 API 新实例或代理
		/// </summary>
		/// <typeparam name="API">要代理的远程类型</typeparam>
		/// <returns>双向回调的 API 新实例或代理</returns>
		public static API CreateCallbackApi<API>() where API : class
		{
			var oc = OperationContext.Current;
			if (oc == null)
			{
				var api = MethodInvoker.GetImplementByType(typeof(API)) as API;
				if (api != null)
					return new MethodInvokerLocaleProxy<API>(api).GetTransparentProxy() as API;

				return null;
			}

			var mi = oc.GetCallbackChannel<IMethodInvoker>();
			if (mi == null)
				return null;

			return new MethodInvokerRemoteCallbackProxy<API>(mi).GetTransparentProxy() as API;
		}

		/// <summary>
		/// 创建双向回调的 API 新实例或代理
		/// </summary>
		/// <typeparam name="API">要代理的远程类型</typeparam>
		/// <param name="closingEvent">关闭事件委托</param>
		/// <param name="faultedEvent">错误事件委托</param>
		/// <returns>双向回调的 API 新实例或代理</returns>
		public static API CreateCallbackApi<API>(EventHandler closingEvent, EventHandler faultedEvent) where API : class
		{
			var oc = OperationContext.Current;
			if (oc == null)
			{
				var api = MethodInvoker.GetImplementByType(typeof(API)) as API;
				if (api != null)
					return new MethodInvokerLocaleProxy<API>(api).GetTransparentProxy() as API;

				return null;
			}

			if (oc.Channel != null)
			{
				if (closingEvent != null)
					oc.Channel.Closing += closingEvent;
				if (faultedEvent != null)
					oc.Channel.Faulted += faultedEvent;
			}
			var mi = oc.GetCallbackChannel<IMethodInvoker>();
			if (mi == null)
				return null;

			return new MethodInvokerRemoteCallbackProxy<API>(mi).GetTransparentProxy() as API;
		}

		/// <summary>
		/// 当前处理的对象
		/// </summary>
		public object CurrentHandler
		{
			get
			{
				return CMessage.ThreadHandler;
			}
		}

		/// <summary>
		/// 当前处理的消息
		/// </summary>
		public IMethodMessage CurrentMessage
		{
			get
			{
				return CMessage.ThreadMessage;
			}
		}

		/// <summary>
		/// 设置附属数据
		/// </summary>
		/// <param name="api">代理实例。</param>
		/// <param name="key">键</param>
		/// <param name="value">值</param>
		/// <returns>值</returns>
		public static object SetData(object api, string key, object value)
		{
			if (api == null)
				return null;

			var proxy = RemotingServices.GetRealProxy(api) as MethodInvokerProxy;//IDictionary<string, object>;//
			if (proxy != null)
			{
				if (proxy.Message != null && proxy.Message.LogicalCallContext != null)
					proxy.Message.LogicalCallContext.SetData(key, value);
				proxy[key] = value;
				return value;
			}

			var dic = api as IDictionary<string, object>;//MethodInvokerProxy
			if (dic != null)
			{
				dic[key] = value;
				return value;
			}

			if (CMessage.ThreadMessage != null)
				return CMessage.SetThreadData(key, value);

			return null;
		}

		/// <summary>
		/// 获取附属数据
		/// </summary>
		/// <param name="api">代理实例。</param>
		/// <param name="key">键</param>
		/// <returns>值</returns>
		public static object GetData(object api, string key)
		{
			if (api == null)
				return null;

			var proxy = RemotingServices.GetRealProxy(api) as MethodInvokerProxy;//IDictionary<string, object>;//
			if (proxy != null)
			{
				if (proxy.Message != null && proxy.Message.LogicalCallContext != null)
				{
					api = proxy.Message.LogicalCallContext.GetData(key);
					if (api != null)
						return api;
				}
				return proxy[key];
			}

			var dic = api as IDictionary<string, object>;//MethodInvokerProxy
			if (dic != null)
				return dic[key];

			if (CMessage.ThreadMessage != null)
				return CMessage.GetThreadData(key);

			return null;
		}
	}
}
